﻿using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web.Mvc;
using EmitMapper;
using InnovaApp.Layers.CommonLayer.Models;
using InnovaApp.Layers.DataLayer;
using InnovaApp.Layers.DomainLayer;
using InnovaApp.Layers.ResourcesLayer.Properties;
using INNOVACALL.Framework.Common;
using INNOVACALL.Framework.Common.Models.MetaModels;
using INNOVACALL.Framework.Common.MVCHelpers;
using INNOVACALL.Framework.Common.MVCHelpers.Localization;

namespace InnovaApp.Layers.CommonLayer.Controllers
{
	/// <summary>
	/// Controler base de common layer
	/// </summary>
	/// <typeparam name="T"></typeparam>
	public abstract class _Controllers_Base<T> : INNOVACALL.Framework.Common.Controllers._Controllers_Base<T> where T : INNOVACALL.Framework.Common.Models._Models_Base
	{
		#region  Variables membres
		private T _contentData;
		#endregion
		private List<string> jQueryvalues = new List<string>();
		private List<string> jQuerycssvalues = new List<string>();

		private string lienConfig = "";
		public T ContentData
		{
			get
			{
				return _contentData;
			}
			set
			{
				_contentData = value;
			}
		}




		#region Private members

		private DataRepositories _dataContext = null;

		#endregion

		public _Controllers_Base() : base() { }

		/// <summary>
		/// Initilializations the view (Framework Step 1) YOU MUST USE InitView and NOT InitializeView if you use _Layout.cshtml
		/// </summary>
		/// <param name="contentData">The content data.</param>
		[CacheManager(enCacheMode.NoCache)]
		protected void InitView(
            string pageTitle,
            string pageMessage,
            string[] specificCssCollection,
            string[] specificJSCollection,
            string[] dynamicJSCollection,
            string[] specificJqueryJSCollection,
            string[] jsVariables,
            string[] externalCss,
            Dictionary<enMeta, string> metaToAdd,
            DataRepositories _dataContext,
            bool displayMenus
        )
		{
            this.ContentData = base.ContentData;
            var contentData = ContentData as _Models_Base;
            FeedMenus(contentData, _dataContext);
            base.InitilializationView(pageTitle, pageMessage, specificCssCollection, specificJSCollection, dynamicJSCollection, specificJqueryJSCollection, jsVariables, externalCss, displayMenus, metaToAdd);
        }

		/// <summary>
        /// Feed menu data directely in the _Models_Base
		/// </summary>
		/// <param name="contentData"></param>
		/// <param name="_dataContext"></param>
        protected void FeedMenus(_Models_Base contentData, DataRepositories _dataContext)
		{
			List<LayoutMenu> dbMenus = _dataContext.LayoutMenu_Rep.Query(x => !x.FK_LayoutMenu.HasValue).ToList();
			List<LayoutMenu> dbSubMenus;

			if (dbMenus.Count > 0)
			{
				contentData._Menus = dbMenus.Select
					(
						x =>
						ObjectMapperManager.DefaultInstance.GetMapper<LayoutMenu, LayoutMenuElement_MetaModel>().Map(x)
					).OrderBy(x => x.SortIndex).ToList();

				foreach (LayoutMenuElement_MetaModel menu in contentData._Menus)
				{
					var mName = CommonLocalization.LookupResource(typeof(Resources), menu.Name);
					menu.Name = (mName == null ? menu.Name : mName);

					dbSubMenus = _dataContext.LayoutMenu_Rep.Query(x => x.FK_LayoutMenu == menu.Id).ToList();
					if (dbSubMenus.Count > 0)
					{
						FeedSubMenus(menu, dbSubMenus, _dataContext);
					}
				}
			}

		}

        /// <summary>
        /// Complement of previous method
        /// </summary>
        /// <param name="menu"></param>
        /// <param name="dbMenus"></param>
        /// <param name="_dataContext"></param>
		private void FeedSubMenus(LayoutMenuElement_MetaModel menu, List<LayoutMenu> dbMenus, DataRepositories _dataContext)
		{
			List<LayoutMenu> dbSubMenus;

			menu.SousMenus = dbMenus.Select
			(
				x =>
				ObjectMapperManager.DefaultInstance.GetMapper<LayoutMenu, LayoutMenuElement_MetaModel>().Map(x)
			).OrderBy(x => x.SortIndex).ToList();

			foreach (LayoutMenuElement_MetaModel sousmenu in menu.SousMenus)
			{
				var mNenu = CommonLocalization.LookupResource(typeof(Resources), sousmenu.Name);
				sousmenu.Name = (mNenu == null ? sousmenu.Name : mNenu);

				dbSubMenus = _dataContext.LayoutMenu_Rep.Query(x => x.FK_LayoutMenu == sousmenu.Id).ToList();
				if (dbSubMenus.Count > 0)
				{
					FeedSubMenus(sousmenu, dbSubMenus, _dataContext);
				}

			}
		}

		/// <summary>
		/// Ensure Data Context closed and disposed before disposing
		/// </summary>
		/// <param name="disposing"></param>
        protected override void Dispose(bool disposing)
		{
			if (_dataContext != null)
			{
				_dataContext.Dispose();
			}
			base.Dispose(disposing);
		}

		/// <summary>
		/// Remove indentation in code
		/// </summary>
		/// <param name="content"></param>
		/// <param name="contentType"></param>
		/// <param name="contentEncoding"></param>
		/// <returns></returns>
        protected override ContentResult Content(string content, string contentType, System.Text.Encoding contentEncoding)
		{
			return base.Content(content.Replace("\t", string.Empty), contentType, contentEncoding);
		}

		/// <summary>
        /// VERY IMPORTANT Method used to return partial views as string in Ajax responses.
        /// </summary>
		/// <returns></returns>
        protected string RenderPartialViewToString()
		{
			return RenderPartialViewToString(null, null);
		}

		/// <summary>
        /// VERY IMPORTANT Method used to return partial views as string in Ajax responses.
        /// </summary>
		/// <param name="viewName"></param>
		/// <returns></returns>
        protected string RenderPartialViewToString(string viewName)
		{
			return RenderPartialViewToString(viewName, null);
		}

		/// <summary>
		/// Do not use
		/// </summary>
		/// <param name="model"></param>
		/// <returns></returns>
        protected string RenderPartialViewToString(object model)
		{
			return RenderPartialViewToString(null, model);
		}

		/// <summary>
		/// VERY IMPORTANT Method used to return partial views as string in Ajax responses.
		/// </summary>
		/// <param name="viewName"></param>
		/// <param name="model"></param>
		/// <returns></returns>
        protected string RenderPartialViewToString(string viewName, object model)
		{
			string toReturn;
			if (string.IsNullOrEmpty(viewName))
				viewName = ControllerContext.RouteData.GetRequiredString("action");

			ViewData.Model = model;

			using (StringWriter sw = new StringWriter())
			{
				ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
				ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
				viewResult.View.Render(viewContext, sw);
				toReturn = sw.GetStringBuilder().ToString();
				return toReturn;
			}
		}
	}
}
